/// @file FluidParticle.cpp
/// inherited from the Particle class and used to represent the fluid particles in the simulation

#include "FluidParticle.h"

FluidParticle::FluidParticle() : Particle()
{
    FluidParticle(0);
}

FluidParticle::FluidParticle
            (
                const FluidParticle& _particle
            ) :
            Particle
            (
                _particle.getId(),
                _particle.getMass(),
                _particle.getPosition(),
                _particle.getColour(),
                _particle.getRadius(),
                _particle.getMoveable(),
                _particle.getVelocity(),
                _particle.getAcceleration(),
                _particle.getNetForce()
            )
{
    m_name = _particle.getName();

    m_density = _particle.getDensity();
    m_materialRestDensity =_particle.getMaterialRestDensity();

    m_pressure = _particle.getPressure();

    m_viscosityConstant = _particle.getViscosityConstant();
    m_gasConstant = _particle.getGasConstant();

    m_surfaceTensionCoefficient = _particle.getSurfaceTensionCoefficient();
    m_surfaceTensionThreshold = _particle.getSurfaceTensionThreshold();
    m_surfaceColorCoefficient = _particle.getSurfaceColorCoefficient();

    m_interfaceTensionCoefficient = _particle.getInterfaceTensionCoefficient();
    m_interfaceTensionThreshold = _particle.getInterfaceTensionThreshold();
    m_interfaceColorCoefficient = _particle.getInterfaceColorCoefficient();

    m_hasHitEnvironmentYet = _particle.m_hasHitEnvironmentYet;
    m_waitUntilFirstHitBoundary = _particle.m_waitUntilFirstHitBoundary;
    m_waitUntilFirstHitRBD = _particle.m_waitUntilFirstHitRBD;
}

FluidParticle::FluidParticle
            (
                const int _id,
                const ngl::Real _mass,
                const ngl::Real _density,
                const ngl::Vector _position,
                const ngl::Vector _velocity,
                const ngl::Real _viscosityConstant,
                const ngl::Real _gasConstant,
                const ngl::Real _surfaceTensionCoefficient,
                const ngl::Real _surfaceTensionThreshold,
                const ngl::Real _surfaceColorCoefficient,
                const ngl::Real _interfaceTensionCoefficient,
                const ngl::Real _interfaceTensionThreshold,
                const ngl::Real _interfaceColorCoefficient,
                const ngl::Colour _colour,
                const ngl::Real _radius,
                const std::string _name,
                const bool _waitUntilFirstHitBoundary,
                const bool _waitUntilFirstHitRBD
            ) :
            Particle(_id, _mass, _position, _colour, _radius, true, _velocity)
{
    //init params
    m_name = _name;

    m_density = _density;
    m_materialRestDensity = _density;

    m_pressure = 0;

    m_viscosityConstant = _viscosityConstant;
    m_gasConstant = _gasConstant;

    m_surfaceTensionCoefficient = _surfaceTensionCoefficient;
    m_surfaceTensionThreshold = _surfaceTensionThreshold;
    m_surfaceColorCoefficient = _surfaceColorCoefficient;

    m_interfaceTensionCoefficient = _interfaceTensionCoefficient;
    m_interfaceTensionThreshold = _interfaceTensionThreshold;
    m_interfaceColorCoefficient = _interfaceColorCoefficient;

    m_hasHitEnvironmentYet = false;
    m_waitUntilFirstHitBoundary = _waitUntilFirstHitBoundary;
    m_waitUntilFirstHitRBD = _waitUntilFirstHitRBD;
}

FluidParticle::~FluidParticle()
{
}

void FluidParticle::calculatePressure()
{
    //modified ideal gas state equation
    m_pressure = m_gasConstant * (m_density - m_materialRestDensity);
}

void FluidParticle::resetForce()
{
    Particle::resetForce();

    m_pressureForce = 0;
    m_viscosityForce = 0;
    m_surfaceTensionForce = 0;
    m_gravityForce = 0;
}

void FluidParticle::updateHitForTheFirstTime
                    (
                        const bool _hitBoundary,
                        const bool _hitRBD
                    )
{
    //assume no hit for the first time
    bool hit1 = false;
    bool hit2 = false;

    //access hit status for both boundary and rbd
    if (m_waitUntilFirstHitBoundary && _hitBoundary )hit1 = true;
    if (m_waitUntilFirstHitRBD && _hitRBD )hit2 = true;

    //either boundary hit or rbd hit implies hit for the first time has occured
    m_hasHitEnvironmentYet = hit1 || hit2;
}
